﻿using System.Linq;
using System.Web.Mvc;

namespace TSharp.Core.Mvc.Web
{
    public class SiteRazerViewEngine : RazorViewEngine
    {
        protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
        {
            return base.CreatePartialView(controllerContext, partialPath);
        }
    }

    /// <summary>
    ///     <para>2010/10/19</para>
    ///     <para>THINKPADT61</para>
    ///     <para>tangjingbo</para>
    /// </summary>
    public class SiteWebFormViewEngine : WebFormViewEngine
    {
        private static readonly string[] _MasterLocationFormats = new[]
                                                                      {
                                                                          "/Views/{1}/{0}.master",
                                                                          "/Views/Shared/{0}.master"
                                                                      };

        private static readonly string[] _AreaMasterLocationFormats = new[]
                                                                          {
                                                                              "/Areas/{2}/Views/{1}/{0}.master",
                                                                              "/Areas/{2}/Views/Shared/{0}.master",
                                                                          };

        private static readonly string[] _ViewLocationFormats = new[]
                                                                    {
                                                                        "/Views/{1}/{0}.aspx",
                                                                        "/Views/{1}/{0}.ascx",
                                                                        "/Views/Shared/{0}.aspx",
                                                                        "/Views/Shared/{0}.ascx"
                                                                    };

        private static readonly string[] _AreaViewLocationFormats = new[]
                                                                        {
                                                                            "/Areas/{2}/Views/{1}/{0}.aspx",
                                                                            "/Areas/{2}/Views/{1}/{0}.ascx",
                                                                            "/Areas/{2}/Views/Shared/{0}.aspx",
                                                                            "/Areas/{2}/Views/Shared/{0}.ascx",
                                                                        };

        private static string GetThemeAndCulturePrefixPath(ControllerContext context)
        {
            var sp = AopContext.GetDefaultLactor().Get<ISiteProvider>();
            string basePath = string.Empty;
            if (sp.EnableTheme && sp.EnableCulture)
                basePath = string.Format("~/{0}/{1}", sp.GetCurrentCultureInfo().Name, sp.GetCurrentTheme().Name);
            else if (sp.EnableCulture)
                basePath = string.Format("~/{0}", sp.GetCurrentCultureInfo().Name);
            else if (sp.EnableTheme)
                basePath = string.Format("~/{0}", sp.GetCurrentTheme().Name);
            else
                basePath = "~";
            return basePath;
        }

        /// <summary>
        ///     使用指定的控制器上下文和母版视图名称来查找指定的视图。
        /// </summary>
        /// <param name="controllerContext">控制器上下文。</param>
        /// <param name="viewName">视图的名称。</param>
        /// <param name="masterName">母版视图的名称。</param>
        /// <param name="useCache">若为 true，则使用缓存的视图。</param>
        /// <returns>页视图。</returns>
        /// <exception cref="T:System.ArgumentNullException">
        ///     <paramref name="controllerContext" /> 参数为 null（在 Visual Basic 中为 Nothing）。
        /// </exception>
        /// <exception cref="T:System.ArgumentException">
        ///     <paramref name="viewName" /> 参数为 null 或空。
        /// </exception>
        public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName,
                                                  string masterName, bool useCache)
        {
            MasterLocationFormats = GetMasterLocationFormats(controllerContext);
            ViewLocationFormats = GetViewLocationFormats(controllerContext);
            PartialViewLocationFormats = GetPartialViewLocationFormats(controllerContext);

            AreaMasterLocationFormats = GetAreaMasterLocationFormats(controllerContext);
            AreaViewLocationFormats = GetAreaViewLocationFormats(controllerContext);
            AreaPartialViewLocationFormats = GetAreaPartialViewLocationFormats(controllerContext);

            return base.FindView(controllerContext, viewName, masterName, useCache);
        }

        /// <summary>
        ///     使用指定的控制器上下文查找指定的分部视图。
        /// </summary>
        /// <param name="controllerContext">控制器上下文。</param>
        /// <param name="partialViewName">分部视图的名称。</param>
        /// <param name="useCache">若为 true，则使用缓存的分部视图。</param>
        /// <returns>分部视图。</returns>
        /// <exception cref="T:System.ArgumentNullException">
        ///     <paramref name="controllerContext" /> 参数为 null（在 Visual Basic 中为 Nothing）。
        /// </exception>
        /// <exception cref="T:System.ArgumentException">
        ///     <paramref name="partialViewName" /> 参数为 null 或空。
        /// </exception>
        public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName,
                                                         bool useCache)
        {
            MasterLocationFormats = GetMasterLocationFormats(controllerContext);
            ViewLocationFormats = GetViewLocationFormats(controllerContext);
            PartialViewLocationFormats = GetPartialViewLocationFormats(controllerContext);

            AreaMasterLocationFormats = GetAreaMasterLocationFormats(controllerContext);
            AreaViewLocationFormats = GetAreaViewLocationFormats(controllerContext);
            AreaPartialViewLocationFormats = GetAreaPartialViewLocationFormats(controllerContext);

            return base.FindPartialView(controllerContext, partialViewName, useCache);
        }

        #region View

        private static string[] GetViewLocationFormats(ControllerContext controllerContext)
        {
            return
                _ViewLocationFormats.Select(x => { return GetThemeAndCulturePrefixPath(controllerContext) + x; })
                                    .ToArray();
        }

        private static string[] GetMasterLocationFormats(ControllerContext controllerContext)
        {
            return
                _MasterLocationFormats.Select(x => { return GetThemeAndCulturePrefixPath(controllerContext) + x; })
                                      .ToArray();
        }

        private static string[] GetPartialViewLocationFormats(ControllerContext controllerContext)
        {
            return GetViewLocationFormats(controllerContext);
        }

        #endregion

        #region AreaView

        /**********************/

        private static string[] GetAreaMasterLocationFormats(ControllerContext controllerContext)
        {
            return
                _AreaMasterLocationFormats.Select(x => { return GetThemeAndCulturePrefixPath(controllerContext) + x; })
                                          .ToArray();
        }

        private static string[] GetAreaViewLocationFormats(ControllerContext controllerContext)
        {
            return
                _AreaViewLocationFormats.Select(x => { return GetThemeAndCulturePrefixPath(controllerContext) + x; })
                                        .ToArray();
        }

        private static string[] GetAreaPartialViewLocationFormats(ControllerContext controllerContext)
        {
            return GetAreaViewLocationFormats(controllerContext);
        }

        /**********************/

        #endregion
    }
}